package com.cman777.springc.ratelimiter.alg;

import com.cman777.springc.ratelimiter.alg.storage.RedisStorage;
import com.cman777.springc.ratelimiter.rule.RateRule;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author chenzhicong
 * @time 2020/9/17 17:27
 * 固定时间算法
 */
@Slf4j
public class FixedTimeAlg implements Alg {
    private RateRule rateRule;
    private RedisStorage redisStorage;
    private String val;

    public FixedTimeAlg(RateRule rateRule, RedisStorage redisStorage,String val) {
        this.rateRule = rateRule;
        this.redisStorage = redisStorage;
        this.val = "RATE_LIMIT_"+rateRule.getId()+"_"+val;
    }

    private boolean tryAcquire4RedisStorage() {
        try {
            redisStorage.setIfAbsent(val, 0L, rateRule.getUnit(), TimeUnit.SECONDS);
            long thisCount = redisStorage.incrementAndGet(val);
            if(thisCount == 1){
                //重新设置下过期时间，因为担心上面两步第二步还没执行完key就过期了,导致过期时间未生效
                redisStorage.expire(val, rateRule.getUnit(),TimeUnit.SECONDS);
            }
            return thisCount <= rateRule.getLimitTimes();
        } catch (Exception e) {
            //防止redis报错系统就不可用。
            log.error(e.getMessage(), e);
            return true;
        }
    }

    @Override
    public boolean tryAcquire() {
        if (redisStorage != null) {
            return tryAcquire4RedisStorage();
        }
        return true;
    }
}
